package org.global.basic.tree;

import org.global.basic.Sort;
import org.global.utils.BeansUtils;

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class TreeService {
    /**
     *
     * @param treeMetas 接受的列表参数，一个树的源数据包含自身标识和父级的标识
     * @param dClass 需要返回的类型
     * @return TreeMeta类型整理成一个树形列表，并返回这个树形列表
     * @throws NoSuchMethodException 这俺不懂
     */
    public <P extends TreeMeta, D extends TreeItem<D>> List<D> levelTree(List<P> treeMetas, Class<D> dClass) throws NoSuchMethodException {
        Constructor<D> constructor = dClass.getConstructor();
        Map<String, D> dMap = treeMetas.stream()
                .collect(Collectors.toMap(
                        TreeMeta::id,
                        (treeMeta -> {
                            try {
                                D d = constructor.newInstance();
                                BeansUtils.copy(treeMeta, d);
                                return d;
                            } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
                                throw new RuntimeException(e);
                            }
                        })
                ));
        List<D> top = new ArrayList<>();
        for (TreeMeta treeMeta : treeMetas) {
            String pid = treeMeta.pid();
            if (pid == null) top.add(dMap.get(treeMeta.id()));
            else {
                D d = dMap.get(pid);
                if (d != null) {
                    if (d.children() == null) d.setChildren(new ArrayList<>());
                    d.children().add(dMap.get(treeMeta.id()));
                } else {
                    top.add(dMap.get(treeMeta.id()));
                }
            }
        }
        return top;
    }

    public <D extends TreeItem<D>> void treeSort(List<D> list) {
        if (list == null) return;
        for (int i = 0; i < list.size(); i++) {
            list.sort(Comparator.comparingInt(TreeItem::sort));
            treeSort(list.get(i).children());
        }
    }
}
